<?php
namespace app\api\controller;

class WeixinGzh extends Base
{
    // 是否静默授权
    protected $isOnlyOpenid;
    
    // 微信支付回调URL
    protected $notifyUrl;
    
    // 当前时间戳
    protected $timeStamp;
    
    // 随机数
    protected $nonce;
    
    // 入口验证KEY
    protected $accessKey;

    function __construct()
    {
        $this->accessKey = config('custom.accessKey');
        $this->timeStamp = time();
        $this->nonce = mt_rand(10000, 99999);
        $this->isOnlyOpenid = true;
        $this->notifyUrl = 'http://api.wei-yong.com/wx_notify';
    }

    /**
     * 微信支付参数配置 - 调用支付时调用
     * @param number $admin_id      客户ID
     */
    public function wxPayConfig($admin_id)
    {
        $field = 'id, appid, secret, pay_mchid, pay_key, gzh_appid, gzh_secret';
        $res = db('customer')->where(['id'=>$admin_id])->field($field)->find();
        
        if ( ! $res) {
            err('', 'ACCOUNT NULL');
        }
        
        // 公众号和小程序使用同一个商户
        $pay_mchid = $res['pay_mchid'];
        $pay_secret = $res['pay_key'];
        $appid = $res['gzh_appid'];
        $secret = $res['gzh_secret'];
        
        define('CUS_WX_APPID', $appid);
        define('CUS_WX_APPSECRET', $secret);
        define('CUS_WX_MCHID', $pay_mchid);
        define('CUS_WX_KEY', $pay_secret);
        define('CUS_WX_SSLCERT', VENDOR_PATH . 'Wxpay/cert/' . $res['id'] . '_cert.pem'); // ../cert/apiclient_cert.pem
        define('CUS_WX_SSLKEY', VENDOR_PATH . 'Wxpay/cert/' . $res['id'] . '_key.pem'); // ../cert/apiclient_key.pem
    }

    /**
     * 公众号微信授权登陆
     */
    public function login()
    {
        $appid = input('get.appid');
        $accreditWay = input('get.accredit_way'); // 0默认授权，1获取用户头像等信息
        
        if (empty($appid)) {
            err('', '缺少参数');
        }
        
        // 是否获取用户头像、昵称等信息
        if (!empty($accreditWay)) {
            if ($accreditWay > 0) {
                $this->isOnlyOpenid = true;
            } else {
                $this->isOnlyOpenid = false;
            }
        }
        
        // 测试 - 清除sessoin
        //session('gzh_userinfo', null);

        // 数据保存在session，不用每次都去请求
        if (session('?gzh_userinfo')) {
            $userinfo = session('gzh_userinfo');
        } else {
            // 获取微信code
            if ( ! input('code')) {
                $redirect_uri = "http://api.wei-yong.com/api/weixin/zghWxLogin?appid=$appid";
                $this->_getWeixinCode($appid, $redirect_uri);
                // 已经退出
            }
            
            // 查询客户ID是否存在
            $info = db('customer')->where(['gzh_appid'=>$appid])->field('id, secret, gzh_appid, gzh_secret, gzh_access_token, gzh_access_token_expires, gzh_redirect_uri')->find();
            
            if ( ! $info) {
                err('', 'PARAM ERROR');
            }
            
            // 根据code，交换userinfo
            $code = input('code');
            $userinfo = $this->_getWeixinUserInfo($code, $info['gzh_appid'], $info['gzh_secret']);
            
            // 查询用户是否创建
            $user = db('user')->where(['openid'=>$userinfo['openid']])->find();
            
            // 创建用户
            if ( ! $user) {
                $data['admin_id'] = $info['id'];
                $data['openid'] = $userinfo['openid'];
                $data['nickname'] = removeEmoji($userinfo['nickname']);
                $data['avatarurl'] = $userinfo['headimgurl'];
                $data['country'] = $userinfo['country'];
                $data['province'] = $userinfo['province'];
                $data['city'] = $userinfo['city'];
                $data['gender'] = $userinfo['sex'];
                $data['language'] = $userinfo['language'];
                $data['create_time'] = $this->timeStamp;
                $id = $user['id'] = db('user')->insertGetId($data);
            }
            
            $mstr = accessEncrypt($info['id'], $user['id'], $this->timeStamp, $info['secret'], $this->accessKey);
            
            $userinfo['mstr'] = $mstr;
            $userinfo['gzh_redirect_uri'] = $info['gzh_redirect_uri'];
            
            // 授权和mstr保存到session，减少重复访问数据库
            session('gzh_userinfo', $userinfo);
        }
        
        // 数据拼接用于前端获取
        $str = "";
        foreach ($userinfo as $key=>$value) {
            if (is_string($value)) {
                $str .= $key . '=' . $value . '&';
            }
        }
        
        $str = rtrim($str, '&');
        $str = urlencode($str);
        
        // 跳转到指定页面
        $this->redirect($userinfo['gzh_redirect_uri'] . "?$str");
        exit();
    }

    /**
     * 重定向获取微信用户code
     * 
     * @param string $appid         微信appid
     * @param string $redirect_uri  跳转url
     */
    public function _getWeixinCode($appid, $redirect_uri)
    {
        $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?';
        $url .= 'appid=' . $appid;
        $url .= '&redirect_uri=' . urlencode($redirect_uri);
        $url .= '&response_type=code';
        if ($this->isOnlyOpenid) {
            $url .= '&scope=snsapi_base';
        } else {
            $url .= '&scope=snsapi_userinfo';
        }
        $url .= '&state=STATE#wechat_redirect';
        
        header('location:' . $url);
        exit();
    }

    /**
     * 根据用户code获取用户信息
     * @param string $code      微信返回code
     * @param string $appid     微信appid
     * @param string $secret    微信secret
     */
    public function _getWeixinUserInfo($code, $appid, $secret)
    {
        $rs = file_get_contents('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $secret . '&code=' . $code . '&grant_type=authorization_code');
        
        $arr = json_decode($rs, true);
        if ( ! empty($arr['openid'])) {
            session('openid', $arr['openid']);
        }
        
        if ( ! isset($arr['access_token'])) {
            dump($arr);
            die();
        }
        
        $rs1 = file_get_contents('https://api.weixin.qq.com/sns/userinfo?access_token=' . $arr['access_token'] . '&openid=' . $arr['openid'] . '&lang=zh_CN');
        
        $userinfo = json_decode($rs1, true);
        return $userinfo;
    }

    /**
     * 对外返回access_token、ticket、过期时间
     * 
     * @param string $appid     公众号appid
     * @return json
     */
    public function accessTokenReturn()
    {
        $appid = input('get.appid');
        
        if (empty($appid)) {
            err('', '缺少参数');
        }
        
        $res = db('customer')->where("gzh_appid = '$appid'")->field('id, gzh_appid, gzh_secret, gzh_access_token, gzh_access_token_expires, gzh_ticket')->find();
        
        if ( ! $res) {
            err('', 'APPID错误');
        }
        
        $access = $this->gzhGetAccessToken($res);
        suc($access, '成功');
    }

    /**
     * 公众号支付
     * @param unknown $dbInfo
     * @param array $payInfo
     */
    public function unifiedOrderGzh($dbInfo, $payInfo = [])
    {
        # 金额不能为空 - 为空会导致签名失败
        if ($dbInfo['amount'] <= 0) {
            err('', 'AMOUNT NULL');
        }
        
        # 引入配置参数
        self::wxPayConfig($dbInfo['admin_id'], 'gzh');
        
        require_once VENDOR_PATH . 'Wxpay/lib/WxPay.Api.php';
        require_once VENDOR_PATH . 'Wxpay/example/log.php';
        require_once VENDOR_PATH . 'Wxpay/example/WxPay.JsApiPay.php';
        
        # 获取openid
        $openid = $this->getOpenid($dbInfo['user_id']);
        
        # 订单号处理
        $orderId = $dbInfo['out_trade_no'];
        
        # 用于判断客户
        $attach = base64_encode("id={$dbInfo['admin_id']}");
        
        # 统一下单
        $tools = new \JsApiPay();
        //$openId = $tools->GetOpenid();
        

        //②、统一下单
        $input = new \WxPayUnifiedOrder();
        //商品描述
        $input->SetBody($dbInfo['subject']);
        //商户订单号
        $input->SetOut_trade_no($orderId);
        //总金额
        $input->SetTotal_fee($dbInfo['amount'] * 100); // 计算总价 - 单位为分
        //通知地址
        $input->SetNotify_url($this->notifyUrl);
        $input->SetAttach($attach); // 自定义参数
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        //$input->SetGoods_tag("");
        //交易类型
        $input->SetTrade_type("JSAPI");
        //用户标识
        $input->SetOpenid($openid);
        
        //dump($input);die;
        //=========步骤3：使用jsapi调起支付============
        $jsApiParameters = \WxPayApi::unifiedOrder($input);
        
        if ($jsApiParameters['return_code'] == 'FAIL') {
            err('', $jsApiParameters['return_msg']);
        }
        
        if ($jsApiParameters['result_code'] == 'FAIL') {
            err($jsApiParameters, '微信创建订单失败');
        }
        
        # 订单信息写入数据库 - 未付款的订单不需要再创建订单数据
        # 订单信息写入数据库 - 未付款的订单不需要再创建订单数据
        if ( ! isset($payInfo['not_create_order'])) {
            $dbInfo['type'] = isset($dbInfo['type']) ? $dbInfo['type']: 2; // 1：货到付款，2：微信支付，3：支付宝支付;
            $dbInfo['openid'] = $openid;
            $dbInfo['out_trade_no'] = $orderId;
            $dbInfo['message'] = isset($dbInfo['message']) ? $dbInfo['message']: ' ';
            $dbInfo['time_start'] = $input->GetTime_start();
            $dbInfo['time_expire'] = $input->GetTime_expire();
            $dbInfo['request_mess'] = json_encode($dbInfo);
            $dbInfo['time_start'] = time();
            db('order')->insert($dbInfo);
        }
        
        $editAddress = $tools->GetJsApiParameters($jsApiParameters);
        return $editAddress;
    }
}